using System.Collections.Generic;
using System.Linq;
using Game.Tile;
using HCore.Utility;
using UnityEngine;

namespace Test
{
    public class TemplateBezierCurve : MonoBehaviour
    {
        // Keep a reference to the point prefab. This prefab 
        // will represent each control point.
        public GameObject PointPrefab;

        // Store the properties of the line.
        public float LineWidth = 0.05f;
        public float LineWidthBezier = 0.05f;
        public Color LineColor = new(0.7f, 0.2f, 0.5f, 0.8f);
        public Color BezierCurveColor = new(0.7f, 0.6f, 0.2f, 0.8f);

        // Keep a list of the points instantiated from the prefab
        // to show the control points.
        private readonly List<GameObject> mPointGameObjects = new();

        // We will also use LineRenderer to show the straight
        // lines connecting these control points as well as
        // the bezier curve based on these control points.
        private LineRenderer[] mLineRenderers;

        // Start is called before the first frame update
        private void Start()
        {
            // Here we will create the actual lines.
            mLineRenderers = new LineRenderer[2];
            mLineRenderers[0] = CreateLine();
            mLineRenderers[1] = CreateLine();

            // Set the name of these lines to distinguish.
            mLineRenderers[0].gameObject.name = "LineRenderer_obj_0";
            mLineRenderers[1].gameObject.name = "LineRenderer_obj_1";

            // Now create the instances of the control points.
            var controlPoints = Tile.GetTemplateControlPoints(100, 20);
            for (var i = 0; i < controlPoints.Count; i++)
            {
                var obj = Instantiate(PointPrefab, controlPoints[i], Quaternion.identity);
                obj.name = "ControlPoint_" + i;
                mPointGameObjects.Add(obj);
            }
        }

        // Update is called once per frame
        private void Update()
        {
            // We will now draw the lines every frame.
            var lineRenderer = mLineRenderers[0];
            var curveRenderer = mLineRenderers[1];

            var pts = mPointGameObjects.Select(t => t.transform.position).Select(dummy => (Vector2)dummy).ToList();

            // set the lineRenderer for showing the straight lines between
            // the control points.
            lineRenderer.positionCount = pts.Count;
            for (var i = 0; i < pts.Count; i++) lineRenderer.SetPosition(i, pts[i]);

            // We can now see the straight lines connecting the control points.
            // We will now proceed to draw the curve based on the bezier points.
            var curve = BezierCurves.GenerateBezierCurves(pts);
            curveRenderer.startColor = BezierCurveColor;
            curveRenderer.endColor = BezierCurveColor;
            curveRenderer.positionCount = curve.Count;
            curveRenderer.startWidth = LineWidthBezier;
            curveRenderer.endWidth = LineWidthBezier;

            for (var i = 0; i < curve.Count; i++) curveRenderer.SetPosition(i, curve[i]);
        }

        // Let's create a function to create the line renderer.
        private LineRenderer CreateLine()
        {
            var obj = new GameObject();
            var lr = obj.AddComponent<LineRenderer>();
            lr.material = new Material(Shader.Find("Sprites/Default"));
            lr.startColor = LineColor;
            lr.endColor = LineColor;
            lr.startWidth = LineWidth;
            lr.endWidth = LineWidth;
            return lr;
        }
    }
}